﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;
using Utilities;

namespace UILibrary
{
    public class CustomActionPane
    {
        private IntPtr m_hAppWnd = IntPtr.Zero;
        private IntPtr m_hPaneWnd = IntPtr.Zero;
        public ActionPane m_actionPane;
        private int m_paneWidth;

        public CustomActionPane(IntPtr hAppWnd, IntPtr hPaneWnd)
        {
            m_hAppWnd = hAppWnd;
            m_hPaneWnd = hPaneWnd;
            m_actionPane = new ActionPane(this.release);
        }

        private IntPtr m_oldWndProc = IntPtr.Zero;
        private Win32Declaration.WndProcDelegate m_newProc = null;

        float dpi;

        private void fitWindow(IntPtr hParentWnd, IntPtr hWnd)
        {
            Win32Declaration.RECT rc;
            Win32Declaration.GetClientRect(hParentWnd, out rc);
            Win32Declaration.MoveWindow(hWnd, rc.Left, rc.Top, rc.Right - rc.Left, rc.Bottom - rc.Top, true);
            Win32Declaration.BringWindowToTop(hWnd);
        }

        private int MineWndProc(IntPtr hWnd, uint msg, int wParam, int lParam)
        {
            switch (msg)
            {
                case Win32Declaration.WM_UPDATE_PARENT:
                    Win32Declaration.SetParent(m_actionPane.Handle, m_hPaneWnd);
                    fitWindow(m_hPaneWnd, m_actionPane.Handle);
                    break;

                //if new window is opened (user creates new workbook or open) then task_pane recreates all childs
                // and we need to set parent again after all previous controls been created
                case Win32Declaration.WM_PARENTNOTIFY:
                    if ((UInt32)wParam == Win32Declaration.WM_CREATE)
                        Win32Declaration.PostMessage(m_hPaneWnd, (UInt32)Win32Declaration.WM_UPDATE_PARENT, IntPtr.Zero, IntPtr.Zero);
                    break;

                case Win32Declaration.WM_RESIZE_PANE:
                    fitWindow(hWnd, m_actionPane.Handle);
                    break;

                case Win32Declaration.WM_WINDOWPOSCHANGED:
                    Win32Declaration.PostMessage(m_hPaneWnd, (UInt32)Win32Declaration.WM_RESIZE_PANE, IntPtr.Zero, IntPtr.Zero);
                    break;
            }

            return Win32Declaration.CallWindowProc(m_oldWndProc, hWnd, msg, wParam, lParam);
        }

        private void subclassActionPane()
        {
            // as soon as we set parent we can forget about handle maximize / minimize
            Win32Declaration.SetParent(m_actionPane.Handle, m_hPaneWnd);

            m_newProc = new Win32Declaration.WndProcDelegate(MineWndProc);
            m_oldWndProc = Win32Declaration.SetWindowLong(m_hPaneWnd, Win32Declaration.GWL_WNDPROC, m_newProc);
        }

        public void buildActionPane()
        {
            subclassActionPane();

            Win32Declaration.RECT rc;
            Win32Declaration.GetClientRect(m_hPaneWnd, out rc);
            MatchWordSize(rc.Left, rc.Top, rc.Right - rc.Left, rc.Bottom - rc.Top);

            // we show in maximized state so we can don't worry about fitting
            System.Drawing.Graphics g = m_actionPane.CreateGraphics();
            dpi = g.DpiX;

            m_actionPane.Show();

            fitWindow(m_hPaneWnd, m_actionPane.Handle);
        }
        
        public void release()
        {
            Win32Declaration.SetWindowLong(m_hPaneWnd, Win32Declaration.GWL_WNDPROC, m_oldWndProc);
        }

        private void MatchWordSize(double top, double left, double width, double height)
        {
            m_actionPane.Top = (int)top;
            m_actionPane.Left = (int)left;
            m_actionPane.Height = (int)height;
            m_actionPane.Width = (int)width;
        }
    }
}
